一列隊伍可以變千手觀音,也可以變海浪。
陣列是最早期和重要的資料結構之一,有許多程式都會用到陣列。我們也會拿陣列來實作許多其他的資料結構,像是列表(list)以及字串(string)。
或許是陣列排序的特性,有如電腦中記憶體的一維陣列結構,而索引就像是記憶體的位址是連續的,因此編譯器通常可以針對陣列操作進行最佳化處理。代表順序的索引(index)會有其對應的值(元素),利用這種特性,我們可以輕易的找到某個指定的索引,再來對值做處理。且在一個陣列裡,我們可以放大量的資料,所以當我們要對這一大串的資料做處理,就可以以「批次」的方式,快速地進行處理。
昨天我們有稍微的提到,在陣列裡我們可以塞下許多不同類型的資料,雖然一般而言,我們會建議陣列裡放的資料最好具有相同資料型別,要對裡面的元素處理也比較單純,但就像我們買了一個承重量只有500g的紙袋,也會遇到ㄧ定要撐到爆的時候,有些時候我們也會在陣列裡放下許多類型的資料 (什麼心態啊~)。但為了批次處理,還是盡量讓陣列裡的資料結構的元素同型別吧,不然得要經過層層的預處理,反而失去陣列可以批次處理的方便特性。
為什麼在陣列裡的元素,具有相同資料型別很重要,來看看 Javascript 會怎麼處理這些不同型別的資料就知道。比如說,一個陣列裡,元素皆是數字(Number),如何把這個陣列裡的數字相加得到總和?只要一個 for 迴圈就可輕易辦到,但如果其中一個陣列元素,長得和其他人不一樣,那麼會有什麼結果呢?
Javascript 弱型別語言的特性,常會給我們神奇的傑克!我們來看以下的這些例子,以 for 迴圈來相加陣列裡面的數字,看看如果在陣列裡夾雜了其他型別的元素,會有什麼結果:
第一個是正常的陣列,裡面的元素皆是數字(number)。
相加陣列裡的數字,總和是 6。
let a =[1,2,3]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // 6
陣列裡夾著一個「偽數字」的字串,會是 33 ,因為加到這個字串的時候加法就失效了,只好把字串 3 硬加上去站隔壁,就成了 33 了。
let a =[1,2,"3"]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // 33
但是如果把「偽數字」的字串放在陣列的第一個,JavaScript 會把其他的數字也當成是字串處理,結果就是把原本 sum 初始化的 0 繼續和其他數字(已變成字串) 堆疊排排站。
let b =["1",2,3]
let sum = 0
for (let i = 0; i < b.length; i++) {
sum = sum + b[i];
}
console.log (sum); // 0123
把其他數字自動轉換成字串的狀況,只會出現在 + 的運算子上 (好偏心),如果是減、乘、除呢?答案是 JavaScript 會自動把字串轉成數字,「偽數字」的字串依放在陣列的位置不同,而有不同的結果,這點還蠻讓人驚訝的。
let a =["1",2,3]
let sum = 1;
for (let i = 0; i < a.length; i++) {
sum = sum * a[i];
}
console.log (sum); // 6
JavaScript 會先相加前面的數字,加到字串時發現無法加了,也無法轉數字,就只好用停在那裡,請字串站旁邊。
let a = [1,2,"Hi"]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // 3Hi
這一定是個失誤,會把另一個陣列放進去累加,然而 JavaScript 很不領情的只接受第一個元素,其他的就放生了。
let a = [1,2,[1,2,3]]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // 31,2,3
在陣列裡放了個 undefined,就什麼也不用加了,直接告訴我們,你不是數字。
let a =[1,2,undefined]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // NaN
再來試試看空值的 null,結果是有比較正常,JavaScript 直接把 null 當成 0,而且無論是放在陣列的頭或尾,都會把 null 當成 0。
let a =[1,2,null]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // 3
因為對 JavaScript 而言,false 的另一個含義是 0,而 true 則代表 1,也因此 1+2+1=4 。當然如果是 false 總和就會是 3。
let a =[1,2,true]
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum = sum + a[i];
}
console.log (sum); // 4 true=1
以上做了那麼多的測試,只是想告訴大家如果陣列的型別不一,處理起來有多麼多的彩蛋,尤其是 JavaScript 弱型別的特色,即使型別不同拿來運算,也不會報錯,實在是蠻可怕的,所以趁此機會了解一下 Javascript 的古怪,也是挺好的,不是嗎?
況且今天測試的也只是資料型別 Primitive 原始型別裡的 Number 而已,等到我們遇到了複合型(composite)或參考型(reference)的資料類型,就要要開始燒腦了。恰巧 JavaScript 的 Array 陣列就是燒腦的型別,但 Array 也是用來存取大量數據的好工具,所以還是很值得好好學習的。
如有需要改進的地方,拜託懇求請告知,我會盡量快速度修改,感謝您~